package com.mryan.auth.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.mryan.auth.dao.AccountDao;
import com.mryan.auth.dao.AuthDao;
import com.mryan.auth.pojo.Account;
import com.mryan.auth.pojo.Auth;
import com.mryan.auth.pojo.Message;
import com.mryan.auth.service.AuthService;
import com.mryan.auth.util.HttpUtil;
import com.mryan.auth.util.IPUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.UUID;

/**
 * @description： AuthServiceImpl
 * @Author MRyan
 * @Date 2021/6/14 16:56
 * @Version 1.0
 */
@Service
public class AuthServiceImpl implements AuthService {

    private Logger logger = LoggerFactory.getLogger(AuthServiceImpl.class);


    @Autowired
    private AuthDao authDao;

    @Autowired
    private AccountDao accountDao;

    @Override
    public Message addAuthInfo(HttpServletRequest request) {
        // 通过UUID生成随机的token
        String qrCodeId = UUID.randomUUID().toString().replaceAll("-", "");
        // 通过IPUtil获取客户端的真实IP地址
        String ip = IPUtil.getIpAddress(request);
        // 通过获取到的客户端IP地址确定客户端所在地理位置
        String address;
        String url = null;
        if (StringUtils.isNotEmpty(ip)) {
            // 使用baidu接口获取IP地址
            url = "http://api.map.baidu.com/location/ip?ip=" + ip + "&ak=nSxiPohfziUaCuONe4ViUP2N&coor=bd09ll";
        } else {
            // 所以无法通过局域网获得地理位置，因此手动改为外网IP
            String fakeip = "171.209.95.223";
            url = "http://api.map.baidu.com/location/ip?ip=" + fakeip + "&ak=nSxiPohfziUaCuONe4ViUP2N&coor=bd09ll";
        }
        // 通过Http工具访问接口
        String result = HttpUtil.doGet(url);
        // 对返回的数据进行解析
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (jsonObject != null) {
            Integer status = jsonObject.getInteger("status");
            if (status == 0) {
                address = jsonObject.getJSONObject("content").getString("address");
                System.out.println(address);
            } else {
                //解析失败，默认地址
                address = "四川省成都市";
            }
        } else {
            //获取baidu接口数据失败
            address = "四川省成都市";
        }
        // 将token相关信息存入数据库中
        authDao.addAuthInfo(qrCodeId, ip, address);
        // 将token返回给客户端
        return new Message(200, "生成并绑定二维码ID成功", qrCodeId);
    }

    @Override
    public Message bindAuthByDeviceInfo(String deviceInfo, String qrCodeId) {
        authDao.addDeviceInfo(deviceInfo, qrCodeId);
        return new Message(200, "设备信息绑定成功", deviceInfo);
    }

    /**
     * 移动端扫描PC端二维码,获取到二维码ID,移动端带二维码ID+移动端身份信息发送给服务端,
     * 服务端验证身份信息通过后,将二维码ID与身份信息绑定,并生成临时token返回给移动端,二维码状态变为已扫描待确认;
     *
     * @param accountName
     * @param qrCodeId
     * @param isScan
     * @return
     */
    @Override
    public Message getTemporaryToken(String accountName, String qrCodeId, boolean isScan) {
        Auth auth = authDao.checkAuthInfo(qrCodeId);
        try {
            if (ObjectUtils.isNotEmpty(auth)) {
                Account accountInfo = getAccountByName(accountName);
                String temporaryToken = UUID.randomUUID().toString().replaceAll("-", "");
                Integer authState = auth.getAuthState();
                if (isScan && authState == 0 || authState == 2) {
                    //设置accountID 并设置state为正在验证状态 设置临时token
                    authDao.setAuthState(accountInfo.getAccountId(), qrCodeId, 2, temporaryToken);
                }
                return new Message(200, "校验并获取临时Token成功", authDao.getAuthInfoByQRCodeId(qrCodeId));
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return new Message(201, "校验并获取临时Token失败", new Auth());
    }

    /**
     * 根据accountName获取account信息
     *
     * @param accountName
     * @return
     */
    private Account getAccountByName(String accountName) {
        return accountDao.getAccountInfoByName(accountName);
    }

    /**
     * 移动端确认登录,并携带临时token请求服务端,服务端验证临时token通过后,改变二维码状态为已确认并生成PCtoken
     *
     * @param temporaryToken
     * @param accountName
     * @return
     */
    @Override
    public Message getToken(String temporaryToken, String accountName, String qrCodeId) {
        Account accountInfo = getAccountByName(accountName);
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        try {
            Auth auth = authDao.checkToken(temporaryToken, accountInfo.getAccountId(), qrCodeId);
            if (ObjectUtils.isNotEmpty(auth)) {
                Integer authState = auth.getAuthState();
                if (authState == 2 || authState == 0) {
                    //生成token 设置authState状态为已验证
                    authDao.addAuthToken(accountInfo.getAccountId(), token, 1, qrCodeId);
                    //临时token失效
                    authDao.deleteTemporaryToken(accountInfo.getAccountId(), "", qrCodeId);
                }
                return new Message(200, "校验并获取Token成功", authDao.getAuthInfoByQRCodeId(qrCodeId));
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return new Message(201, "校验并获取Token失败", null);
    }


    /**
     * 根据token获取Auth信息
     *
     * @param token
     * @return
     */
    @Override
    public Message getAccountInfoByToken(String token) {
        Auth auth = authDao.getAuthInfoByToken(token);
        // 默认token为3，不存在
        Integer state = 3;
        // 为空则获取信息失败
        if (auth == null) {
            return new Message(201, "获取口令信息失败", new Account());
        }
        // 获得token的状态
        state = auth.getAuthState();
        if (state != 1 && state == 3) {
            return new Message(201, "获取口令信息失败 状态过期", new Account());
        }
        Account accountInfoById = accountDao.getAccountInfoById(auth.getAccountId());
        Account account = new Account();
        account.setAccountId(accountInfoById.getAccountId());
        account.setAccountAvatar(accountInfoById.getAccountAvatar());
        account.setAccountName(accountInfoById.getAccountName());
        account.setAccountPhone(accountInfoById.getAccountPhone());
        if (account == null) {
            return new Message(201, "获取口令信息失败", new Account());
        }
        return new Message(200, "获取口令信息成功", account);
    }

    @Override
    public Message getAuthInfo(String qrCodeId) {
        //tokenState：0等待验证，1验证成功，2正在验证，3验证失败（过期）
        // 默认token为3，不存在
        Integer state = 3;
        Auth auth = authDao.getAuthInfoByQRCodeId(qrCodeId);
        if (null != auth) {
            // 获得token的状态
            state = auth.getAuthState();
        }
        Message message = new Message();
        HashMap<String, Object> hashMap = new HashMap<>();
        // token状态为1，验证成功
        if (state == 1) {
            message.setCode(200);
            message.setMessage("使用口令成功");
            hashMap.put("state", 1);
            hashMap.put("auth", auth);
        } else if (state == 3) {
            // token状态为3，失效
            message.setCode(201);
            message.setMessage("使用口令失败 口令失效");
            hashMap.put("state", 3);
            hashMap.put("auth", new Auth());
        } else if (state == 2) {
            //扫码成功，请在手机上确认
            message.setCode(200);
            message.setMessage("使用口令成功");
            hashMap.put("state", 2);
            hashMap.put("auth", auth);
        } else {
            message.setCode(201);
            message.setMessage("等待验证");
            hashMap.put("state", 0);
            hashMap.put("auth", new Auth());
        }
        message.setData(hashMap);
        return message;
    }


}
